package VideoProcessing;

import java.awt.Dimension;
import java.awt.image.WritableRaster;

import javax.media.format.VideoFormat;

public class LabelEffect extends RgbVideoEffect {
	private static final byte NONE = (byte) 255;
	Dimension size;

	@Override
	protected boolean processRGB(byte[] bin, byte[] bout, VideoFormat format) {
		size = format.getSize();
		for (int i = 0; i < bin.length; i++) {
			if (bin[i] == 1) {
				bout[i] = 0;
			} else {
				bout[i] = NONE;
			}
		}
		horizantalLabel(bout);
		scanLeftTop2RightBottom(bout);
		scanRightBottom2LeftTop(bout);
		int max = 0;
		for (int i = 0; i < bout.length; i++) {
			if (byte2Int(bout[i]) > max)
				max = byte2Int(bout[i]);
		}
		//System.out.println(max);
		return true;
	}

	private void scanRightBottom2LeftTop(byte[] bout) {
		final int N = 4;
		byte[] ox = { 1, 1, 0, -1 };
		byte[] oy = { 0, 1, 1, 1 };
		for (int y = size.height - 1; y >= 0; y--) {
			for (int x = size.width - 1; x >= 0; x--) {
				int index = y * size.width + x;
				if (bout[index] != NONE) {
					byte label = NONE;
					for (int k = 0; k < N; k++) {
						int tx, ty;
						tx = x + ox[k];
						ty = y + oy[k];
						if (inBoundry(tx, ty, size.width, size.height)
								&& bout[ty * size.width + tx] != NONE) {
							label = bout[ty * size.width + tx];
							break;
						}
					}
					if (label != NONE) {
						bout[index] = label;
					}
				}
			}
		}
	}

	private void scanLeftTop2RightBottom(byte[] bout) {
		final int N = 4;
		byte[] ox = { -1, -1, 0, 1 };
		byte[] oy = { 0, -1, -1, -1 };
		for (int y = 0; y < size.height; y++) {
			for (int x = 0; x < size.width; x++) {
				int index = y * size.width + x;
				if (bout[index] != NONE) {
					byte label = NONE;
					for (int k = 0; k < N; k++) {
						int tx, ty;
						tx = x + ox[k];
						ty = y + oy[k];
						if (inBoundry(tx, ty, size.width, size.height)
								&& bout[ty * size.width + tx] != NONE) {
							label = bout[ty * size.width + tx];
							break;
						}
					}
					if (label != NONE) {
						bout[index] = label;
					}
				}
			}
		}
	}

	private void horizantalLabel(byte[] bout) {
		byte label = 0;
		for (int y = 0; y < size.height; y++) {
			for (int x = 0; x < size.width; x++) {
				int index = y * size.width + x;
				if (bout[index] == 0) {
					if (x == 0 || bout[index - 1] == NONE) {
						label++;
						bout[index] = label;
					} else {
						bout[index] = bout[index - 1];
					}
				}
			}
		}
	}

	private boolean inBoundry(int tx, int ty, int width, int width2) {
		return (0 <= tx && tx < size.width) && (0 <= ty && ty < size.height);
	}

	@Override
	public String getName() {
		return "Label";
	}
	protected void updateImage(byte[] bout, VideoFormat vformat) {
		synchronized (displayImage) {
			// // Copy pixels to image
			WritableRaster rast = displayImage.getRaster();
			int[] pixel = new int[] { 0, 0, 0, 255 };
			int p = 0;
			for (int y = vformat.getSize().height - 1; y >= 0; y--) {
				for (int x = 0; x < vformat.getSize().width; x++) {
					pixel[0] = pixel[1] = pixel[2] = bout[p++];
					rast.setPixel(x, y, pixel);
				}
			}
		}
	}
}
